﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using Terminal.Advanced_AEUC_settings_controls.Settings_AUX;
using System.Windows.Forms;

namespace Terminal.Advanced_AEUC_settings_controls.Scripting
{
    class ScrInvokeScriptFile : ScrBasicAction
    {
        /// <summary>
        /// Public constructor for the script action
        /// </summary>
        /// <param name="iDispName">Action display text</param>
        /// <param name="iUsageHelp">Usage help and comments text for the action</param>
        public ScrInvokeScriptFile(string iDispName, string iUsageHelp)
            : base(iDispName, iUsageHelp)
        {
            usageHelp += "Input params: path to script file.\n";
        }

        ScrRunTimeEnv rte = null;
        int lastCmdLine = 0;

        void invk_OnScriptExecLineChange(string ErrorStatus)
        {
            if(lastCmdLine < rte.crntCmdLine)
                rte.scrStepProgBar(rte.progBar_InvkScrWorkAround);
        }

        /// <summary>
        /// Perform the action using specified parameters.
        /// </summary>
        /// <param name="paramList">List of the input/output parameters for the action</param>
        /// <returns>True if action is succesful</returns>
        public override bool Do(List<object> paramList)
        {
            rte = null;
            lastCmdLine = 0;

            if (breakPoint)
                WaitUserInput();

            if (paramList.Count > 0 && paramList[0].GetType() == typeof(ScrRunTimeEnv))
            {
                rte = (ScrRunTimeEnv)(paramList[0]);
                string scrFile = new string(((char[])(paramList[1])));

                FileInfo finf = new FileInfo(scrFile);

                if (!finf.Exists)
                {
                    DirectoryInfo dirScript = null;
                    try
                    {
                        dirScript = new DirectoryInfo(ScriptModule.Properties.Settings.Default.FastScriptMenuFolder);
                    }
                    catch
                    {
                        dirScript = null;
                    }

                    if (dirScript == null || !dirScript.Exists)
                    {
                        dirScript = new DirectoryInfo(Application.StartupPath + ScriptingModule.SCRIPT_DIR);
                    }

                    if (!dirScript.Exists)
                    {
                        return false;
                    }

                    finf = new FileInfo(dirScript.FullName + scrFile);
                }
                if (finf.Exists)
                {
                    ScrRunTimeEnv savedRte = rte.Clone();
                    rte = new ScrRunTimeEnv();
                    rte.condExecution = ScrRunTimeEnv.CondExecMode.NORMAL;
                    rte.runningMode = ScrRunTimeEnv.RunMode.FREE_RUN;
                    rte.crntCmdLine = 0;
                    rte.trgtCmdLine = -1;
                    rte.updateComp = savedRte.updateComp;
                    rte.Print = savedRte.Print;
                    rte.scrExec = savedRte.scrExec;
                    rte.scrSourcesify = savedRte.scrSourcesify;
                    rte.scrSetRte = savedRte.scrSetRte;
                    rte.SilentRun = true;

                    rte.scrSetUpProgBar = savedRte.scrSetUpProgBar;
                    rte.scrStepProgBar = savedRte.scrStepProgBar;
                    rte.scrRemProgBar = savedRte.scrRemProgBar;

                    savedRte.CopyScriptEvents(rte, ScrRunTimeEnv.ScrEvents.CompUpdate | ScrRunTimeEnv.ScrEvents.Done | ScrRunTimeEnv.ScrEvents.Terminating);
                    rte.OnScriptExecLineChange += new ScrMainModule.ScriptEvent(invk_OnScriptExecLineChange);

                    rte.scrSetRte(rte);
                    try
                    {
                        TextReader txRd = new StreamReader(finf.OpenRead());
                        rte.cmdLns = (txRd.ReadToEnd().Replace('\r', '\n')).Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);

                        rte.progBar_InvkScrWorkAround = rte.scrSetUpProgBar("Invoking script file: " + finf.Name, rte.cmdLns.Length);

                        rte.scrExec();

                        rte.scrRemProgBar(rte.progBar_InvkScrWorkAround);

                        rte.scrSetRte(savedRte);
                        uint result = (uint)rte.rteResult;
                        rte = savedRte;

                        rte.InvokeEnded = true;

                        if (result == 0)
                            return true;
                        else
                            return false;
                    }
                    catch
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }

            return false;
        }
        /// <summary>
        /// Returns a List containing objects of the parameter list required for the Do function.
        /// </summary>
        /// <returns>List of parameter objects</returns>
        public override List<Type> GetParamList()
        {
            List<Type> paramList = new List<Type>();
            paramList.Add(typeof(ScrRunTimeEnv));
            paramList.Add(typeof(char[]));

            return paramList;
        }

        /// <summary>
        /// Generate C source code for specified parameters
        /// </summary>
        /// <param name="paramlist">List of input/output parameters for the action</param>
        /// <returns>C source string</returns>
        public override string GenerateSourceCode(List<object> paramList)
        {
            if (paramList.Count > 0 && paramList[0].GetType() == typeof(ScrRunTimeEnv))
            {
                ScrRunTimeEnv rte = (ScrRunTimeEnv)(paramList[0]);
                string scrFile = new string(((char[])(paramList[1])));

                FileInfo finf = new FileInfo(scrFile);

                if (!finf.Exists)
                {
                    DirectoryInfo dirScript = null;
                    try
                    {
                        dirScript = new DirectoryInfo(ScriptModule.Properties.Settings.Default.FastScriptMenuFolder);
                    }
                    catch
                    {
                        dirScript = null;
                    }

                    if (dirScript == null || !dirScript.Exists)
                    {
                        dirScript = new DirectoryInfo(Application.StartupPath + ScriptingModule.SCRIPT_DIR);
                    }

                    if (!dirScript.Exists)
                    {
                        return "Can't generate source - check script file!";
                    }

                    finf = new FileInfo(dirScript.FullName + scrFile);
                }
                if (finf.Exists)
                {
                    ScrRunTimeEnv savedRte = rte.Clone();
                    rte = new ScrRunTimeEnv();
                    rte.condExecution = ScrRunTimeEnv.CondExecMode.NORMAL;
                    rte.runningMode = ScrRunTimeEnv.RunMode.FREE_RUN;
                    rte.crntCmdLine = 0;
                    rte.trgtCmdLine = -1;
                    rte.updateComp = savedRte.updateComp;
                    rte.Print = savedRte.Print;
                    rte.scrExec = savedRte.scrExec;
                    rte.scrSourcesify = savedRte.scrSourcesify;
                    rte.scrSetRte = savedRte.scrSetRte;
                    rte.SilentRun = true;

                    rte.scrSetRte(rte);
                    try
                    {
                        TextReader txRd = new StreamReader(finf.OpenRead());
                        rte.cmdLns = (txRd.ReadToEnd().Replace('\r', '\n')).Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);

                        rte.scrSourcesify();

                        rte.scrSetRte(savedRte);

                        if ((string)rte.rteResult == "true")
                            return rte.c_source;
                        else
                            return "Can't generate source - check script file!";
                    }
                    catch
                    {
                        return "Can't generate source - check script file!";
                    }
                }
                else
                {
                    return "Can't generate source - check script file!";
                }
            }

            return "Can't generate source - check script file!";
        }

        /// <summary>
        /// Returns a List containing objects of the parameter list required for the GenerateSourceCode function.
        /// </summary>
        /// <returns>List of parameter objects</returns>
        public virtual List<Type> GetParamListSourceGen()
        {
            List<Type> paramList = new List<Type>();
            paramList.Add(typeof(ScrRunTimeEnv));
            paramList.Add(typeof(char[]));

            return paramList;
        }
    }
}

